package com.example.demo.service.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.example.demo.config.AlipayConfig;
import com.example.demo.dao.IOrderInfoRepository;
import com.example.demo.entity.OrderInfo;
import com.example.demo.service.IOrderInfoService;
import com.example.demo.utils.JsonUtils;
import com.example.demo.utils.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * Created by Hy on 2018/8/21.
 */
@Service
public class OrderInfoService implements IOrderInfoService{
    private static Logger log = LoggerFactory.getLogger(OrderInfoService.class);
    @Autowired
    private IOrderInfoRepository infoRepository;
    @Autowired
    private AlipayConfig alipayConfig;
    @Autowired
    private AlipayClient alipayClient;

    private static List<String> statusList = Arrays.asList("WAIT_BUYER_PAY","TRADE_CLOSED","TRADE_SUCCESS","TRADE_FINISHED");

    /**
     * 生成订单
     * @param subject 订单名称
     * @param body 订单描述
     * @param money 支付金额
     * @param sellerId 收款商户ID
     * @return
     */
    @Override
    public OrderInfo createOrder(String subject, String body, float money, String sellerId) {
        //生成商户订单号
        String orderId = RandomUtils.time();

        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setOrderId(orderId);
        orderInfo.setSubject(subject);
        orderInfo.setBody(body);
        orderInfo.setMoney(money);
        orderInfo.setSellerId(sellerId);
        orderInfo.setCreateDate(new Date());
        /**
         * 订单状态与官方统一
         * WAIT_BUYER_PAY:交易创建，等待卖家付款
         * TRADE_CLOSED:未付款交易超时关闭，或支付完成后全额退款
         * TRADE_SUCCESS:交易支付成功
         * TRADE_FINISHED:交易结束，不可退款
         */
        orderInfo.setStatus(statusList.get(0));
        infoRepository.save(orderInfo);
        return orderInfo;
    }

    /**
     * 校验订单
     * 支付宝同步/异步回调时调用
     * @param params
     * @return
     * @throws Exception
     */
    @Override
    public boolean validOrder(Map<String, String> params) throws Exception {
        /**
         * 实际验证过程建议商户务必添加以下校验：
         * 1.需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
         * 2.判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
         * 3.校验通知中的seller_id(或者seller_email)是否为out_trade_no这笔单据的对应的操作方(有时候，一个商户可能有多个seller_id/seller_email)
         * 4.验证app_id是否为该商户本身。
         */
        //1.调用sdk验证签名
        boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(), "utf-8", alipayConfig.getSignType());
        if(!signVerified){
            return false;
        }
        //获取订单数据
        String orderId = params.get("out_trade_no");
        OrderInfo orderInfo = infoRepository.findByOrderId(orderId);
        if(orderInfo ==null){
            return false;
        }
        //2.判断金额是否相等
        float money = Float.parseFloat(params.get("total_amount"));
        if(money != orderInfo.getMoney()){
            return false;
        }

        //3.判断商户ID是否相等
        String sellerId = params.get("seller_id");
        if(!sellerId.equals(orderInfo.getSellerId())){
            return false;
        }

        //4.判断APP_ID是否相等
        String appId = params.get("app_id");
        if(!appId.equals(alipayConfig.getAppId())){
            return false;
        }
        return true;
    }

    @Override
    public OrderInfo getByIdOrAlipayNo(String orderId, String alipayNo) {
        if(StringUtils.isNotBlank(orderId)){
            OrderInfo orderInfo = infoRepository.findByOrderId(orderId);
            if(orderInfo!=null){
                return orderInfo;
            }
        }

        if(StringUtils.isNotBlank(alipayNo)){
            List<OrderInfo> orderInfoList = infoRepository.findByAlipayNo(alipayNo);
            if(orderInfoList!=null && orderInfoList.size()>0){
                return orderInfoList.get(0);
            }
        }
        return null;
    }

    @Override
    public boolean changeStatus(String orderId, String status, String... tradeNo) {
        //判断参数是否合法
        OrderInfo orderInfo = infoRepository.findByOrderId(orderId);
        if(orderInfo == null){
            return false;
        }

        if(StringUtils.isBlank(status) || !statusList.contains(status)){
            return false;
        }

        //如果订单状态相同，不发生改变
        if(status.equals(orderInfo.getStatus())){
            return true;
        }

        //如果是TRADE_SUCCESS,设置订单号
        if("TRADE_SUCCESS".equals(status) && tradeNo.length> 0 ){
            orderInfo.setAlipayNo(tradeNo[0]);
        }

        orderInfo.setStatus(status);
        infoRepository.saveAndFlush(orderInfo);
        return true;
    }

    @Override
    public boolean syncStatus(String orderId, String alipayNo) {
        OrderInfo orderInfo = getByIdOrAlipayNo(orderId, alipayNo);
        if(orderInfo == null){
            return false;
        }

        //1.设置请求参数
        AlipayTradeQueryRequest alipayRequest = new AlipayTradeQueryRequest();
        Map<String,String> map = new HashMap<>(16);
        map.put("out_trade_no",orderId);
        map.put("trade_no",alipayNo);
        alipayRequest.setBizContent(JsonUtils.objectToJson(map));

        //2.请求
        try {
            String json = alipayClient.execute(alipayRequest).getBody();
            Map<String,Object> resMap = JsonUtils.jsonToPojo(json, Map.class);
            Map<String,String> responseMap = (Map)resMap.get("alipay_trade_query_response");

            //获取返回状态码
            String code = responseMap.get("code");
            if("10000".equals(code)){
                //当查询的订单状态不等于数据库订单状态时，更新状态
                String tradeStatus = responseMap.get("trade_status");
                if(!orderInfo.getStatus().equals(tradeStatus)){
                    orderInfo.setStatus(tradeStatus);
                    infoRepository.saveAndFlush(orderInfo);
                    return true;
                }
            }else{
                log.error("【状态同步Service】错误码：{},错误信息：{}",code,responseMap.get("sub_msg"));
            }
            return true;
        } catch (Exception e) {
            log.error("【状态同步Service】异常，错误信息：{}",e.getMessage());
            e.printStackTrace();
        }

        return false;
    }
}
